//
//  YZNetworkManager.m
//  VET
//
//  Created by Lam BG on 2018/6/26.
//  Copyright © 2018年 YZ. All rights reserved.
//

#import "YZNetworkManager.h"
#import "RACNetworking.h"
#import "YZLauncher.h"
#import "YZUser.h"

#define kTokenInvalidate 401

@implementation YZNetworkManager

SingletonM

#pragma mark - Requset Handel

- (RACSignal*)requestURL:(NSString*)url whitParams:(NSDictionary *)params withHeaders:(NSDictionary *)headers withMethod:(YZHTTPMethod)method {
    
    RACSignal *requestSignal = nil;
    switch (method) {
            
        case POST:
        {
            requestSignal = [self postURL:url whitParams:params withHeaders:headers];
        }
            break;
            
        case PUT:
        {
            requestSignal = [self putURL:url whitParams:params withHeaders:headers];
        }
            break;
            
        case DELETE:
        {
            requestSignal = [self deleteURL:url whitParams:params withHeaders:headers];
        }
            break;
            
        case PATCH:
        {
            requestSignal = [self patchURL:url whitParams:params withHeaders:headers];
        }
            break;
            
        default:
        {
            // Get
//            NSMutableString *urlLink = [NSMutableString string];
//            [urlLink appendFormat:@"%@", url];
//            [params.allKeys enumerateObjectsUsingBlock:^(NSString *key, NSUInteger idx, BOOL * _Nonnull stop) {
//                [urlLink appendFormat:@"/%@", params[key]];
//            }];
            requestSignal = [self getURL:url whitParams:params withHeaders:headers];
        }
            break;
    }
    
    return requestSignal;
}

- (RACSignal*)getURL:(NSString*)url whitParams:(NSDictionary *)params withHeaders:(NSDictionary *)headers {
    
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        // 添加公共参数
        NSDictionary *requsetParams = [self commonParameterHandel:params andHeaders:headers];
        
        [[[RACNetworking sharedInstance] getURL:url whitParams:requsetParams] subscribeNext:^(NSDictionary *jsonData) {
            
            // 统一处理下一步
            [self handelNext:subscriber responseData:jsonData requestURL:url requestParams:params];
            
        } error:^(NSError * _Nullable error) {
            
            // 统一处理错误
            [self handelError:subscriber responseError:error requestURL:url requestParams:params];
        }];
        
        return [RACDisposable disposableWithBlock:^{}];
    }];
}

- (RACSignal*)postURL:(NSString*)url whitParams:(NSDictionary *)params withHeaders:(NSDictionary *)headers {
    
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        // 添加公共参数
        NSDictionary *requsetParams = [self commonParameterHandel:params andHeaders:headers];
        
        [[[RACNetworking sharedInstance] postURL:url whitParams:requsetParams] subscribeNext:^(NSDictionary *jsonData) {
            
            // 统一处理下一步
            [self handelNext:subscriber responseData:jsonData requestURL:url requestParams:params];
            
        } error:^(NSError * _Nullable error) {
            
            // 统一处理错误
            [self handelError:subscriber responseError:error requestURL:url requestParams:params];
        }];
        
        return [RACDisposable disposableWithBlock:^{}];
    }];
}

- (RACSignal*)putURL:(NSString*)url whitParams:(NSDictionary *)params withHeaders:(NSDictionary *)headers {
    
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        // 添加公共参数
        NSDictionary *requsetParams = [self commonParameterHandel:params andHeaders:headers];
        
        [[[RACNetworking sharedInstance] putURL:url whitParams:requsetParams] subscribeNext:^(NSDictionary *jsonData) {
            
            // 统一处理下一步
            [self handelNext:subscriber responseData:jsonData requestURL:url requestParams:params];
            
        } error:^(NSError * _Nullable error) {
            
            // 统一处理错误
            [self handelError:subscriber responseError:error requestURL:url requestParams:params];
        }];
        
        return [RACDisposable disposableWithBlock:^{}];
    }];
}

- (RACSignal*)deleteURL:(NSString*)url whitParams:(NSDictionary *)params withHeaders:(NSDictionary *)headers {
    
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        // 添加公共参数
        NSDictionary *requsetParams = [self commonParameterHandel:params andHeaders:headers];
        
        [[[RACNetworking sharedInstance] deleteURL:url whitParams:requsetParams] subscribeNext:^(NSDictionary *jsonData) {
            
            // 统一处理下一步
            [self handelNext:subscriber responseData:jsonData requestURL:url requestParams:params];
            
        } error:^(NSError * _Nullable error) {
            
            // 统一处理错误
            [self handelError:subscriber responseError:error requestURL:url requestParams:params];
        }];
        
        return [RACDisposable disposableWithBlock:^{}];
    }];
}

- (RACSignal*)patchURL:(NSString*)url whitParams:(NSDictionary *)params withHeaders:(NSDictionary *)headers {
    
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        // 添加公共参数
        NSDictionary *requsetParams = [self commonParameterHandel:params andHeaders:headers];
        
        [[[RACNetworking sharedInstance] patchURL:url whitParams:requsetParams] subscribeNext:^(NSDictionary *jsonData) {
            
            // 统一处理下一步
            [self handelNext:subscriber responseData:jsonData requestURL:url requestParams:params];
            
        } error:^(NSError * _Nullable error) {
            
            // 统一处理错误
            [self handelError:subscriber responseError:error requestURL:url requestParams:params];
        }];
        
        return [RACDisposable disposableWithBlock:^{}];
    }];
}

- (RACSignal*)uploadImgWithUrl:(NSString*)url params:(NSDictionary *)params withHeaders:(NSDictionary *)headers img:(UIImage*)image imgPath:(NSString*)path apiKey:(NSString*)key {
 
    return [RACSignal createSignal:^RACDisposable * _Nullable(id<RACSubscriber>  _Nonnull subscriber) {
        
        // 添加公共参数
        NSDictionary *requsetParams = [self commonParameterHandel:params andHeaders:headers];
        
        [[[RACNetworking sharedInstance] uploadImgWithUrl:url params:requsetParams img:image imgPath:path apiKey:key] subscribeNext:^(NSDictionary *jsonData) {
            
            [subscriber sendNext:jsonData];
            
        } error:^(NSError * _Nullable error) {
            
            [self logWithError:error withUrl:url withParams:params];
            [subscriber sendError:error];
            [subscriber sendCompleted];
        } completed:^{
            
            [subscriber sendCompleted];
        }];
        
        return [RACDisposable disposableWithBlock:^{}];
    }];
}

#pragma mark -- 非RAC

+ (void)uploadImgsWithApi:(NSString*)api params:(NSDictionary *)params imgs:(NSArray<UIImage *> *)images name:(NSString *)name withHeaders:(NSDictionary *)headers success:(YZNetworkCompletionSuccessBlock)successBlock fail:(YZNetworkCompletionFailBlock)failBlock
{
    [[YZNetWorkRequestManager sharedInstance] reqestUploadImgsWithApi:api params:params imgs:images name:name withHeaders:headers success:^(NSObject *obj) {
        if (successBlock) {
            successBlock(obj);
        }
    } fail:^(NSError *error) {
        if (failBlock) {
            failBlock(error);
        }
    }];
}

+ (void)uploadVideoWithApi:(NSString*)api params:(NSDictionary *)params videoPath:(NSString *)videoPath name:(NSString *)name withHeaders:(NSDictionary *)headers success:(YZNetworkCompletionSuccessBlock)successBlock fail:(YZNetworkCompletionFailBlock)failBlock{
    [[YZNetWorkRequestManager sharedInstance] reqestUploadVideoWithApi:api params:params videoPath:videoPath name:name withHeaders:headers success:^(NSObject *obj) {
        if (successBlock) {
            successBlock(obj);
        }
    } fail:^(NSError *error) {
        if (failBlock) {
            failBlock(error);
        }
    }];
}

+ (void)uploadVideoWithApi:(NSString*)api params:(NSDictionary *)params videoUrl:(NSURL *)videoUrl name:(NSString *)name withHeaders:(NSDictionary *)headers success:(YZNetworkCompletionSuccessBlock)successBlock fail:(YZNetworkCompletionFailBlock)failBlock
{
    [[YZNetWorkRequestManager sharedInstance] reqestUploadVideoWithApi:api params:params videoUrl:videoUrl name:name withHeaders:headers success:^(NSObject *obj) {
        if (successBlock) {
            successBlock(obj);
        }
    } fail:^(NSError *error) {
        if (failBlock) {
            failBlock(error);
        }
    }];
}

+ (void)postWithApi:(NSString*)api params:(NSDictionary *)params withHeaders:(NSDictionary *)headers success:(YZNetworkCompletionSuccessBlock)successBlock fail:(YZNetworkCompletionFailBlock)failBlock
{
    [[YZNetWorkRequestManager sharedInstance] requestPostWithApi:api params:params withHeaders:headers success:^(NSObject *obj) {
        if (successBlock) {
            LogDicToJson(obj);
            successBlock(obj);
        }
    } fail:^(NSError *error) {
        if (failBlock) {
            failBlock(error);
        }
    }];
}

+ (void)getWithApi:(NSString*)api params:(NSDictionary *)params withHeaders:(NSDictionary *)headers success:(YZNetworkCompletionSuccessBlock)successBlock fail:(YZNetworkCompletionFailBlock)failBlock
{
    [[YZNetWorkRequestManager sharedInstance] requestGetWithApi:api params:params withHeaders:headers success:^(NSObject *obj) {
        if (successBlock) {
            LogDicToJson(obj);
            successBlock(obj);
        }
    } fail:^(NSError *error) {
        if (failBlock) {
            failBlock(error);
        }
    }];
}

#pragma mark -

// 统一参数
- (NSDictionary*)commonParameterHandel:(NSDictionary *)params andHeaders:(NSDictionary*)headers {
    
//    [params setValuesForKeysWithDictionary:@{@"key" : @"value"}];
    
    for (NSString *key in headers.allKeys) {
        
        [params setValuesForKeysWithDictionary:@{[NSString stringWithFormat:@"%@%@", kHeaderKey, key] : headers[key]}];
    }
    
    return params;
}

- (void)handelNext:(id<RACSubscriber>)subscriber responseData:(NSDictionary*)resut requestURL:(NSString*)url requestParams:(NSDictionary *)params {
    
    LogDicToJson(resut);
    
    // 当数据有返回，判断是否按照规则
    if ([self isAPISuccess:resut]) {
        
        [subscriber sendNext:resut[@"data"]];
        [subscriber sendCompleted];
        
    } else {
        
        NSError *error = [self configAPIError:resut];
        [self logWithError:error withUrl:url withParams:params];
        
        // token 处理
        if (error.code == kTokenInvalidate) {
            
            if([YZUser clearLocalUser]) {
                
                // 回到登录 / 注册页
                [YZLauncher jumpToLaunch];
            }
        }
        
        // 返回规定的错误格式
        [subscriber sendError:error];
        [subscriber sendCompleted];
    }
}

- (void)handelError:(id<RACSubscriber>)subscriber responseError:(NSError*)error requestURL:(NSString*)url requestParams:(NSDictionary *)params {
    
    [self logWithError:error withUrl:url withParams:params];
    [subscriber sendError:error];
    [subscriber sendCompleted];
}

#pragma mark - Error Handel

- (BOOL)isAPISuccess:(NSDictionary *)data {
    
    BOOL successFlag = NO;
    // 当返回值 含有 error 字段 并且为 0 时 表示成功
    if (data != nil && [data objectForKey:@"code"] != nil) {
        
        NSString *responseCode = [data valueForKey:@"code"];
//        responseCode = [responseCode substringToIndex:2];
        if ([responseCode intValue] == 0) {
            
            successFlag = YES;
        }
    }
    
    return successFlag;
}

- (NSError *)configAPIError:(NSDictionary *)data {
    
    NSInteger errorCode = [self configAPIErrorCode:data];
    NSDictionary *errorMessage = [self configAPIErrorInfo:data];

    return [NSError errorWithDomain: @"API Error"
                               code: errorCode
                           userInfo: errorMessage];
}

- (NSInteger)configAPIErrorCode:(NSDictionary *)data {
    
    NSInteger errorCode = -1;
    if (data != nil && [data objectForKey:@"code"] != nil) {
        
        errorCode = [[data valueForKey:@"code"] integerValue];
    }
    
    return errorCode;
}
    
- (NSDictionary *)configAPIErrorInfo:(NSDictionary *)data {
    
    NSDictionary *errorMessage = @{ NSLocalizedDescriptionKey : @"api return empty data" };
    if (data != nil && [data objectForKey:@"message"] != nil) {
        
        errorMessage = @{ NSLocalizedDescriptionKey : [data valueForKey:@"message"] };
    }
    
    return errorMessage;
}

// 打印 api 错误信息
- (void)logWithError:(NSError *)error withUrl:(NSString *)url withParams:(NSDictionary *)params{
    
    NSLog(@" \n----- api error info ------\n Url : %@  \n Params : %@ \n Error : %@ \n ---------------------", url, params, error);
}

#pragma mark - 实时检测网络状态

+ (void)startMonitoring {
    
    [RACNetworking startMonitoring];
}

+ (void)stopMonitoring {
    
    [RACNetworking stopMonitoring];
}

@end














